import { IStageAssetsInfo } from "babylon-lib/base/stage";
import { Scene } from "@babylonjs/core/scene";
import { Camera } from "@babylonjs/core/Cameras/camera";
import { Light } from "@babylonjs/core/Lights/light";
import { RawAssetsUrl, RawData } from "../raw-assets-info";
import { GenerateComponent } from './default-stage-component/generate-component';
import { ILoose } from "babylon-lib/tool/utils";
import { AbstractAssetTaskInfo, GLTFMeshTaskInfo, CubeTextureTaskInfo } from "babylon-lib/loader/asset-task-info";
import * as Data from '../data/data';
import { DetailView } from "babylon-lib/preset/detail-view";
import { IActiveDefaultVRExperienceOptions, IVRContainer } from 'babylon-lib/xr/vr-container';
import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera";
import { Vector3 } from "@babylonjs/core/Maths/math";
import { SEPARATE_NO_ROTATE_HANDEDNESS_CONFIGURATION } from "babylon-lib/xr/vr-motion/vr-motion-movement";
import { XRStage } from "babylon-lib/base/xr-stage";
import { FreezeCamera } from 'babylon-lib/misc/freeze-camera';
import { RenderOrder } from "babylon-lib/misc/render-order";
import { ProgressManager } from "./default-stage-component/process-manager";
import { NotePanel } from "../ui/note-panel";
import { ControlPanel } from "../ui/control-panel";
import { ModelContainer } from './default-stage-component/model-container';
import { DefaultModel } from "./default-stage-component/default-model";
import { UserGestureCapture } from "babylon-lib/misc/user-gesture-capture";


class DefaultStage extends XRStage {

    public actor: IActor = {};
    public xr!: IVRContainer | null;

    protected isProduction(): boolean {
        return Data.isProduction.value;
    }

    protected appName(): string {
        return RawData.appConfig.name;
    }

    protected assetTaskInfos(): ILoose<AbstractAssetTaskInfo> | Array<IStageAssetsInfo> {
        return {
            changjing: new GLTFMeshTaskInfo(RawAssetsUrl.changjing),

            lightCube: new CubeTextureTaskInfo(
                RawAssetsUrl.lightCubePX,
                RawAssetsUrl.lightCubePY,
                RawAssetsUrl.lightCubePZ,
                RawAssetsUrl.lightCubeNX,
                RawAssetsUrl.lightCubeNY,
                RawAssetsUrl.lightCubeNZ,
            ),
        };
    }

    protected getXROptions(): IActiveDefaultVRExperienceOptions {
        return {
            renderingGroupId: RenderOrder.id(RenderOrder.topName),
            cameraOptions: {
                position: Data.cameraPosition.value,
                target: Data.cameraTarget.value,
                maxZ: 1000,
                ellipsoid: new Vector3(0.5, 1.8, 0.5),
                ellipsoidOffset: new Vector3(0, 1.8, 0),
                speed: 0.1,
            },
            disableTeleportation: true,
            enableMovement: true,
            movementOptions: {
                customRegistrationConfigurations: SEPARATE_NO_ROTATE_HANDEDNESS_CONFIGURATION
            }
        };
    }

    protected initializeLights(scenes: Scene[], cameras: Camera[]): Light[] {
        const ls = super.initializeLights(scenes, cameras);
        ls[0].intensity = Data.lightIntensity.value;
        return ls;
    }

    protected generateComponents(scenes: Scene[], cameras: Camera[], lights: Light[]): void {
        /**
         * 自定义
         */
        GenerateComponent.initialize(this);
        this.bindData();
        Data.cameraData.reset(true);
        FreezeCamera.freezePosition(this.mainScene);
        UserGestureCapture.setScene(this.mainScene);
        UserGestureCapture.onDebut(() => {
            ProgressManager.start();
        })
    }

    public async reset(): Promise<void> {
        await super.reset();
        /**
         * 自定义
         */
        Data.rootData.reset();
        Data.cameraData.reset(true);
        FreezeCamera.freezePosition(this.mainScene);
        ProgressManager.reset();
        NotePanel.note();
        ControlPanel.reset();
        ModelContainer.reset();
        DefaultModel.reset();
        UserGestureCapture.reset();
    }

    public resetSight(): void {
        super.resetSight();
        /**
         * 自定义
         */

    }

    public async changeImmersive(inaction?: boolean | undefined): Promise<void> {
        await super.changeImmersive(inaction);
        /**
         * 自定义
         */
        if (!ProgressManager.started) ProgressManager.start();
    }

    private bindData(): void {
        Data.cameraData.onChange(() => {
            this.mainCamera.position = Data.cameraPosition.value;
            (this.mainCamera as FreeCamera).target = Data.cameraTarget.value;
        });
        Data.lightIntensity.onChange((o, n) => {
            this.lights[0].intensity = n;
        });
    }

}

interface IActor {
    detailView?: DetailView,
}

export { DefaultStage };